﻿#ifndef __SS_ASCII_DICTIONARY_H__
#define __SS_ASCII_DICTIONARY_H__
#include "trieTree/ssAsciiTrieTree.h"
#include "../memory/ssTempPtr.h"


namespace StarSeeker
{

template<typename D_VALUE, unsigned char D_KEY_NUM=128>
class ssAsciiDictionary
{
public:
	class Iterator
	{
		friend class ssAsciiDictionary;
	public:
		Iterator() :m_pNode(0)
		{
		}
		Iterator(const Iterator & it) :m_pNode(it.m_pNode)
		{
		}
		Iterator(ssAsciiTrieNode<D_VALUE,D_KEY_NUM>* p) :m_pNode(p)
		{
		}
		bool operator == (const Iterator& it) const
		{
			return this->m_pNode == it.m_pNode;
		}
		bool operator != (const Iterator& it) const
		{
			return this->m_pNode != it.m_pNode;
		}
		void operator = (const Iterator& it)
		{
			this->m_pNode = it.m_pNode;
		}
		void operator ++ ()
		{
			ssAsciiTrieTree<D_VALUE, D_KEY_NUM>* pTree = (ssAsciiTrieTree<D_VALUE, D_KEY_NUM>*)m_pNode->Onwer();
			do 
			{
				m_pNode = pTree->Next();
				if (!m_pNode || m_pNode->Data())
					break;
			} while (m_pNode);
		}
		char Key()
		{
			return m_pNode->Key();
		}
		D_VALUE* Data()
		{
			return m_pNode->Data();
		}
		bool IsVaild() const
		{
			if (!m_pNode)
			{
				return false;
			}
			if (0 == m_pNode->Onwer())
			{
				return false;
			}
			return true;
		}
	private:
		ssAsciiTrieNode<D_VALUE,D_KEY_NUM>*	m_pNode;
	};

	ssPair<Iterator, error_t>	Insert(D_VALUE* val, const char* arr, u32 len=0);
	ssPair<Iterator, error_t>	InsertCover(D_VALUE* val, const char* arr, u32 len=0);
	Iterator					Find(const char* arr, u32 len=0);
	error_t						Erase(Iterator& itr);
	error_t						Erase(const char* arr, u32 len=0);
	void						Clear();
	u32							Size();
	Iterator					Begin();
	Iterator					End();
private:
	ssAsciiTrieTree<D_VALUE,D_KEY_NUM>	m_tree;
};

template<typename D_VALUE,  unsigned char D_KEY_NUM>
inline ssPair<typename ssAsciiDictionary<D_VALUE,D_KEY_NUM>::Iterator, error_t> ssAsciiDictionary<D_VALUE,D_KEY_NUM>::Insert(D_VALUE* val, const char* arr, u32 len)
{
	if (len==0) len = ::strlen(arr);
	ssPair<ssAsciiTrieNode<D_VALUE,D_KEY_NUM>*, error_t> ret = m_tree.Insert(arr, len, val);
	return ssPair<typename ssAsciiDictionary<D_VALUE,D_KEY_NUM>::Iterator, error_t>(ret.first, ret.second);
}

template<typename D_VALUE,  unsigned char D_KEY_NUM>
inline ssPair<typename ssAsciiDictionary<D_VALUE,D_KEY_NUM>::Iterator, error_t> ssAsciiDictionary<D_VALUE,D_KEY_NUM>::InsertCover(D_VALUE* val, const char* arr, u32 len)
{
	if (len == 0) len = ::strlen(arr);
	ssPair<ssAsciiTrieNode<D_VALUE,D_KEY_NUM>*, error_t> ret = m_tree.Insert(arr, len, val);
	if (ret.second==SS_DICT_KEY_EXISTED)
	{
		ret.first.SetData(val);
	}
	return ssPair<typename ssAsciiDictionary<D_VALUE,D_KEY_NUM>::Iterator, error_t>(ret.first, ret.second);
}

template<typename D_VALUE,  unsigned char D_KEY_NUM>
inline typename ssAsciiDictionary<D_VALUE,D_KEY_NUM>::Iterator ssAsciiDictionary<D_VALUE,D_KEY_NUM>::Find(const char * arr, u32 len)
{
	if (len == 0) len = ::strlen(arr);
	return m_tree.Find(arr, len);
}

template<typename D_VALUE,  unsigned char D_KEY_NUM>
inline error_t ssAsciiDictionary<D_VALUE,D_KEY_NUM>::Erase(Iterator & itr)
{
	error_t ret = m_tree.Remove(itr.m_pNode);
	if (ret== SS_DICT_OK)
	{
		itr.m_pNode = 0;
	}
	return ret;
}

template<typename D_VALUE,  unsigned char D_KEY_NUM>
inline error_t ssAsciiDictionary<D_VALUE,D_KEY_NUM>::Erase(const char * arr, u32 len)
{
	if (len == 0) len = ::strlen(arr);
	return m_tree.Remove(arr, len);
}

template<typename D_VALUE,  unsigned char D_KEY_NUM>
inline void ssAsciiDictionary<D_VALUE,D_KEY_NUM>::Clear()
{
	m_tree.Clear();
}

template<typename D_VALUE,  unsigned char D_KEY_NUM>
inline u32 ssAsciiDictionary<D_VALUE,D_KEY_NUM>::Size()
{
	return m_tree.GetCount();
}

template<typename D_VALUE, unsigned char D_KEY_NUM>
inline typename ssAsciiDictionary<D_VALUE, D_KEY_NUM>::Iterator ssAsciiDictionary<D_VALUE, D_KEY_NUM>::Begin()
{
	ssAsciiTrieNode<D_VALUE, D_KEY_NUM>* itr = m_tree.Begin();
	while (itr)
	{
		if (itr->Data())
			break;
	}
	return itr;
}

template<typename D_VALUE, unsigned char D_KEY_NUM>
inline typename ssAsciiDictionary<D_VALUE, D_KEY_NUM>::Iterator ssAsciiDictionary<D_VALUE, D_KEY_NUM>::End()
{
	return m_tree.End();
}

}
#endif
